package com.ray.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.appengine.repackaged.com.google.gson.JsonObject;
import com.ray.exception.ServiceException;
import com.ray.pojo.AccessToken;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;

public class WeiXinUtil {

	
    private static Logger log = LoggerFactory.getLogger(WeiXinUtil.class);  
    //微信的请求url
    //获取access_token的接口地址（GET） 限200（次/天）  
    public final static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}";  
    //获取ticket地址
    public final static String getTicketUrl="https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=";
    //根据code获取用户url
    public final static String codeToUserUrl="https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE";
    //获取code的url
    private  final static String codeUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid=";
    //获取微信公众号授权accessToken的url
    private final static String weiXinPublicNumberCodeUrl="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    //获取微信公众号全局accessToken
    private final static String weiXinPublicNumberGlobalUrl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    //微信扫码登陆全局accessToken
    public final static String weixinScanLoginGetAccessTokenUrl="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

    /**
     * 1.发起https请求并获取结果 
     *  
     * @param requestUrl 请求地址 
     * @param requestMethod 请求方式（GET、POST） 
     * @param outputStr 提交的数据 
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
     */  
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  
        JSONObject jsonObject = null;  
        StringBuffer buffer = new StringBuffer();  
        try {  
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化  
            TrustManager[] tm = { new MyX509TrustManager() };  
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
            sslContext.init(null, tm, new java.security.SecureRandom());  
            // 从上述SSLContext对象中得到SSLSocketFactory对象  
            SSLSocketFactory ssf = sslContext.getSocketFactory();  

            URL url = new URL(requestUrl);  
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
            httpUrlConn.setSSLSocketFactory(ssf);  

            httpUrlConn.setDoOutput(true);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  
            // 设置请求方式（GET/POST）  
            httpUrlConn.setRequestMethod(requestMethod);  

            if ("GET".equalsIgnoreCase(requestMethod)) {
            	httpUrlConn.connect();  
            }

            // 当有数据需要提交时  
            if (null != outputStr) {  
                OutputStream outputStream = httpUrlConn.getOutputStream();  
                // 注意编码格式，防止中文乱码  
                outputStream.write(outputStr.getBytes("UTF-8"));  
                outputStream.close();  
            }  

            // 将返回的输入流转换成字符串  
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  

            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            // 释放资源  
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  
            jsonObject = JSONObject.fromObject(buffer.toString());  
        } catch (ConnectException ce) {  
            log.error("Weixin server connection timed out.");  
        } catch (Exception e) {  
            log.error("https request error:{}", e);  
        }  
        return jsonObject;  
    }  

    /** 
     * 2.发起http请求获取返回结果 
     *  
     * @param requestUrl 请求地址 
     * @return 
     */  
    public static String httpRequest(String requestUrl) {  
        StringBuffer buffer = new StringBuffer();  
        try {  
            URL url = new URL(requestUrl);  
            HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  

            httpUrlConn.setDoOutput(false);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  

            httpUrlConn.setRequestMethod("GET");  
            httpUrlConn.connect();  

            // 将返回的输入流转换成字符串  
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  

            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            // 释放资源  
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  

        } catch (Exception e) {  
        }  
        return buffer.toString();  
    }  


    /** 
     * 3.获取access_token 
     *  
     * @param appid 凭证 
     * @param appsecret 密钥 
     * @return 
     */  
    public static AccessToken getAccessToken(String appid, String appsecret) {  
        AccessToken accessToken = null;  

        String requestUrl = access_token_url.replace("{corpId}", appid).replace("{corpsecret}", appsecret);  
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
        // 如果请求成功  
        if (null != jsonObject) {  
        	//System.out.println(jsonObject);
            try {  
                accessToken = new AccessToken();  
                accessToken.setToken(jsonObject.getString("access_token"));  
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));  
            } catch (JSONException e) {  
                accessToken = null;  
                // 获取token失败  
                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            }  
        }  
     //  System.out.println(accessToken);
        return accessToken;  
    }  

    //获取ticket用于生成签名
    public static String getTicket() throws ServiceException {
    	 String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpID, WeiXinParamesUtil.workSecret).getToken();
         String url=getTicketUrl+accessToken;
         String data=WeiXinUtil.httpRequest(url);
         JSONObject json=JSONObject.fromObject(data);
         String ticket="";
         if(0==json.getInt("errcode")) {
        	 ticket=json.getString("ticket");
         }else {
        	 throw new ServiceException("获取ticket出错");
         }
    	return ticket;
    }
    
    
    
    //获取授权签名
    public static String getJsSdkSign(String noncestr,String tsapiTicket,String timestamp,String url) throws UnsupportedEncodingException{  
        String content="jsapi_ticket="+tsapiTicket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;  
        String ciphertext=null;  
        try {  
        	MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(content.getBytes("UTF-8"));
            ciphertext = byteToHex(crypt.digest());

            
//            ciphertext=byteToStr(digest);  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        }  
        return ciphertext;  
    }  
    
//    public static String byteToStr(byte[] byteArray){  
//        String strDigest="";  
//        for (int i = 0; i < byteArray.length; i++) {  
//            strDigest+=byteToHexStr(byteArray[i]);  
//        }  
//        return strDigest;  
//    }  
//    
    private static String byteToHex(final byte[] hash) {
    	Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
    
    
    
    public static String byteToHexStr(byte mByte){  
        char[] Digit={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};  
        char[] tempArr = new char[2];  
        tempArr[0]=Digit[(mByte>>>4)&0X0F];  
        tempArr[1]=Digit[mByte&0X0F];  
        String s=new String(tempArr);  
        return s;  
    } 
    

    //获取授权code的url
    public static String getCodeUrl(String redirUrl) throws UnsupportedEncodingException {
    	redirUrl=java.net.URLDecoder.decode(redirUrl,"utf-8");
    	StringBuilder sb=new StringBuilder(codeUrl);
    	sb.append(WeiXinParamesUtil.corpID).append("&redirect_uri=").append(redirUrl).append("&response_type=code&scope=snsapi_userinfo&agentid=").append(WeiXinParamesUtil.workAgentId).append("&state=STATE#wechat_redirect");
        //测试
    	//    	sb.append(WeiXinParamesUtil.corpId).append("&redirect_uri=").append(redirUrl).append("&response_type=code&scope=snsapi_userinfo&agentid=").append(WeiXinParamesUtil.agentId).append("&state=STATE#wechat_redirect");
    	return sb.toString();
    }
    
    
    //获取微信公众号静默授权code的url
    public static String getWeiXinPubliucNumberCodeUrl(String redirUrl) throws UnsupportedEncodingException {
    	redirUrl=java.net.URLDecoder.decode(redirUrl,"utf-8");
    	StringBuilder sb=new StringBuilder(codeUrl);
    	sb.append(WeiXinParamesUtil.weiXinPbulicNumberAppId).append("&redirect_uri=").append(redirUrl).append("&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect");
    	return sb.toString();
    }
    
//    通过code获取请求acctoken的url
    public static String getWeiXinPublicNumberCodeToUserUrl(String code) {
    	String url=weiXinPublicNumberCodeUrl.replace("APPID", WeiXinParamesUtil.weiXinPbulicNumberAppId).replace("SECRET", WeiXinParamesUtil.weiXinPbulicNumberAppSecret).replace("CODE", code);
    	return url;
    }
    
//    拼接codeurl
    public static String getCodeToUserUrl(String token,String code) {
    	String url=codeToUserUrl.replace("ACCESS_TOKEN", token).replace("CODE", code);
    	return url;
    }

    //获取微信公众号全局accessToken
	public static String getAccessToken() {
		String url=weiXinPublicNumberGlobalUrl.replace("APPID", WeiXinParamesUtil.weiXinPbulicNumberAppId).replace("APPSECRET", WeiXinParamesUtil.weiXinPbulicNumberAppSecret);
		String json=WeiXinUtil.httpRequest(url);
		System.out.println(url);
		System.out.println(json);
		JSONObject jsonObject=JSONObject.fromObject(json);
		String accessTtoken=jsonObject.getString("access_token");
		return accessTtoken;
	}
	
	//判断用户是否关注
	public static boolean hasSubscribe(String accessToken,String openId) {
		JSONObject object = httpRequest("https://api.weixin.qq.com/cgi-bin/user/info?access_token="+accessToken+"&openid="+openId+"&lang=zh_CN", "GET", null);
		if ("1".equals(object.get("subscribe").toString())) {
			return true;
		}
		return false;
	}
	
	//获取jssdk js-ticket
	public static String getJsSDKTicket(String accessToken) {
		String ticket="";
		String data=WeiXinUtil.httpRequest("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken+"&type=jsapi");
        JSONObject json=JSONObject.fromObject(data); 
	    if(0==json.getInt("errcode")) {
	   	 	ticket=json.getString("ticket");
	    }else {
	   	 	throw new ServiceException("获取ticket出错");
	    }
	    return ticket;
	} 
	
	//获取微信扫码登陆全局accessToken
	public static JSONObject getWeixinScanLoginAccessToken(String code) {
		String url=weixinScanLoginGetAccessTokenUrl.replace("APPID", WeiXinParamesUtil.weixinScanLoginAppId).replace("SECRET", WeiXinParamesUtil.weixinScanLoginAppSecret).replace("CODE", code);
		String json=WeiXinUtil.httpRequest(url);
		System.out.println(url);
		System.out.println(json);
		JSONObject jsonObject=JSONObject.fromObject(json);
		return jsonObject;
	}
	
	public static void main(String[] args) {
		System.out.println(getWeixinScanLoginAccessToken("001nKua62cWzeQ0xqw9626afa62nKuaI"));
	}

}